package com.framework.mapper.generator.godeGenerator.custom;

import com.framework.common.util.hump.HumpOrLineUtil;
import com.framework.common.util.other.NumeralUtil;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.config.TableConfiguration;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import static org.mybatis.generator.internal.util.StringUtility.isTrue;
import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;

/**
 * @author 龘鵺
 * @version 1.0
 * @className com.framework.mapper.generator.godeGenerator.custom
 * @description 自定义实体类视图类生成类
 * @datetime 2022-01-09 11:11:11
 */
public class ModelVoGeneratorPlugin extends PluginAdapter {
    private Map<String, Integer> filterMap = new HashMap<String, Integer>(NumeralUtil.POSITIVE_EIGHT);

    // model项目目录，一般为 src/main/java
    private String modelVoTargetProject;

    // model项目目录，如：com.thinkj2ee.cms.model.service
    private String modelVoPackage;

    // 父类model 前缀
    private String supperModelPreffix;

    // 父类model 后缀
    private String supperModelSuffix;

    // model 前缀
    private String modelVoPreffix;

    // model 后缀
    private String modelVoSuffix;

    //实体类路径
    private String recordType;
    //父类实体类类名 如：SystemButton
    private String modelName;

    //实体类类名 如：systemButton
    private String lowercaseInitialModelName;
    //实体类路径
    private FullyQualifiedJavaType model;

    //supper实体类类名 如：SystemButton
    private String supperModelClassName;
    private String modelClassName;//类路径
    private String nowTime;//时间
    private String author;//开发人
    private String version;//版本号
    private String className;//表名注视 如：按钮
    private String classPath;//类路径
    /**
     * 生成什么端的代码： back=后台端， api=用户端
     */
    private String item = "";

    /**
     * 是否生成业务类 true=是， false=否
     */
    private boolean modelVoStatus = true;

    private String implementsStr = "java.io.Serializable";

    public ModelVoGeneratorPlugin() {
        filterMap.put("operaterStatus", NumeralUtil.POSITIVE_ZERO);
    }

    @Override
    public boolean validate(List<String> warnings) {
        boolean valid = true;

       /* if (!stringHasValue(properties
                .getProperty("targetProject"))) {
            warnings.add(getString("ValidationError.18", 
                    "MapperConfigPlugin", 
                    "targetProject")); 
            valid = false;
        }
        if (!stringHasValue(properties.getProperty("servicePackage"))) { 
            warnings.add(getString("ValidationError.18", 
                    "MapperConfigPlugin", 
                    "servicePackage")); 
            valid = false;
        }
        if (!stringHasValue(properties.getProperty("serviceImplPackage"))) { 
            warnings.add(getString("ValidationError.18", 
                    "MapperConfigPlugin", 
                    "serviceImplPackage")); 
            valid = false;
        }
*/
        modelVoTargetProject = properties.getProperty("modelVoTargetProject");
        supperModelPreffix = properties.getProperty("supperModelPreffix");
        supperModelSuffix = properties.getProperty("supperModelSuffix");
        modelVoPackage = properties.getProperty("modelVoPackage");
        modelVoPreffix = properties.getProperty("modelVoPreffix");
        modelVoPreffix = stringHasValue(modelVoPreffix) ? modelVoPreffix : "";
        modelVoSuffix = properties.getProperty("modelVoSuffix");
        modelVoSuffix = stringHasValue(modelVoSuffix) ? modelVoSuffix : "";
        nowTime = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date());
        author = properties.getProperty("author");
        version = properties.getProperty("version");
        item = properties.getProperty("item");
        modelVoStatus = Boolean.valueOf(properties.getProperty("modelVoStatus"));
        return valid;
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        recordType = introspectedTable.getBaseRecordType();
        modelName = recordType.substring(recordType.lastIndexOf(".") + 1);
        modelClassName = modelVoPackage + "." + modelVoSuffix.toLowerCase() + "." + HumpOrLineUtil.stringToFirstOneUpperCase(modelVoPreffix.toLowerCase()) + modelName + HumpOrLineUtil.stringToFirstOneUpperCase(modelVoSuffix.toLowerCase());
        classPath = modelVoPackage + "." + modelVoSuffix.toLowerCase() + "." + HumpOrLineUtil.stringToFirstOneUpperCase(modelVoPreffix.toLowerCase()) + modelName + HumpOrLineUtil.stringToFirstOneUpperCase(modelVoSuffix.toLowerCase());
        supperModelClassName = modelVoPackage + "." + HumpOrLineUtil.stringToFirstOneUpperCase(supperModelPreffix.toLowerCase()) + modelName + HumpOrLineUtil.stringToFirstOneUpperCase(supperModelSuffix.toLowerCase());
        model = new FullyQualifiedJavaType(recordType);
        className = introspectedTable.getRemarks().lastIndexOf("表") > -1 ? introspectedTable.getRemarks().substring(0, introspectedTable.getRemarks().lastIndexOf("表")) : introspectedTable.getRemarks();
        lowercaseInitialModelName = StringUtils.uncapitalize(modelName);

        List<GeneratedJavaFile> answer = new ArrayList<>();
        if (modelVoStatus) {
            GeneratedJavaFile gjf = generateModelGenerate(introspectedTable);
            answer.add(gjf);
        }


        return answer;
    }

    // 生成实体视图类接口
    private GeneratedJavaFile generateModelGenerate(IntrospectedTable introspectedTable) {
        FullyQualifiedJavaType modelSupper = new FullyQualifiedJavaType(implementsStr);
        FullyQualifiedJavaType modelVo = new FullyQualifiedJavaType(modelClassName);
        TopLevelClass clazz = new TopLevelClass(modelVo);
        clazz.setVisibility(JavaVisibility.PUBLIC);
        // 类 引入的类
        clazz.addImportedType(implementsStr);
        // 类 的实现序列化类
        clazz.addSuperInterface(modelSupper);
        // 继承父类
        clazz.setSuperClass(new FullyQualifiedJavaType(supperModelClassName));
        // 引用对象
        clazz.addImportedType(model);
        clazz.addImportedType(new FullyQualifiedJavaType("com.framework.common.annotation.QueryParam"));
        clazz.addImportedType(new FullyQualifiedJavaType("com.framework.common.annotation.DataTypeTarget"));
        clazz.addImportedType(new FullyQualifiedJavaType("com.framework.common.model.dataType.DataTypeConstant"));

        //类注释
        clazz.addJavaDocLine("/**");
        clazz.addJavaDocLine(" * @author " + author);
        clazz.addJavaDocLine(" * @version " + version);
        clazz.addJavaDocLine(" * @className " + classPath);
        clazz.addJavaDocLine(" * @description " + className + "视图类");
        clazz.addJavaDocLine(" * @datetime " + nowTime);
        clazz.addJavaDocLine(" */");


        MybatisCommentGenerator commentGenerator = (MybatisCommentGenerator) context.getCommentGenerator();
        commentGenerator.setVoSuppressAllComments(false);
        List<IntrospectedColumn> list = introspectedTable.getAllColumns();
        for (IntrospectedColumn item : list) {
            if (filterMap.containsKey(item.getJavaProperty())) {
                continue;
            }
            if (item.getJavaProperty().endsWith("Status")) {
                // 添加全局成员变量
                Field field = new Field(getVariableName(item.getJavaProperty()), FullyQualifiedJavaType.getStringInstance());
                field.setVisibility(JavaVisibility.PRIVATE);
                field.addAnnotation("@DataTypeTarget(type = DataTypeConstant.DATA_TYPE_INT_TO_LEBEL, fields = \"" + item.getJavaProperty() + "\", code = \"" + item.getJavaProperty() + "\")");
                commentGenerator.addFieldComment(field, introspectedTable, item);
                clazz.addField(field);
                // 生成set方法
                Method method = new Method("set" + HumpOrLineUtil.stringToFirstOneUpperCase(getVariableName(item.getJavaProperty())));
                method.setVisibility(JavaVisibility.PUBLIC);
                method.addParameter(new Parameter(FullyQualifiedJavaType
                        .getStringInstance(), getVariableName(item.getJavaProperty())));
//                method.addBodyLine("this." + getVariableName(item.getJavaProperty()) + " = " + getVariableName(item.getJavaProperty()) + ";"); 
                method.addBodyLine(trim(getVariableName(item.getJavaProperty()), item, true)); 
                commentGenerator.addGeneralMethodComment(method, introspectedTable);
                clazz.addMethod(method);                // 生成get方法
                method = new Method("get" + HumpOrLineUtil.stringToFirstOneUpperCase(getVariableName(item.getJavaProperty())));
                method.setVisibility(JavaVisibility.PUBLIC);
                method.setReturnType(FullyQualifiedJavaType.getStringInstance());
                method.addBodyLine("return " + getVariableName(item.getJavaProperty()) + ";");
                commentGenerator.addGeneralMethodComment(method, introspectedTable);
                clazz.addMethod(method);

            }
        }
        commentGenerator.setVoSuppressAllComments(true);
//
//        //描述类的成员属性
//        Field daoField = new Field(daoFieldName, new FullyQualifiedJavaType(daoFieldType));
//        //加入日志代码
//        daoField.addJavaDocLine("private Logger log = LoggerFactory.getLogger(" + serviceImplFieldName + ".class);");
//        //创建mapper申明
//        clazz.addImportedType(new FullyQualifiedJavaType(daoFieldType));
//        clazz.addImportedType(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired"));
//        //描述成员属性 的注解
//        daoField.addAnnotation("@Autowired");
//        //描述成员属性修饰符
//        daoField.setVisibility(JavaVisibility.PRIVATE);
//        clazz.addField(daoField);

        GeneratedJavaFile gjf = new GeneratedJavaFile(clazz, modelVoTargetProject, context.getJavaFormatter());
        return gjf;
    }

    private String getVariableName(String val) {
        return val + "Name";
    }

    private String replaceStr(String str, String... val) {
        return String.format(str, val);
    }

    private String trim(String property, IntrospectedColumn introspectedColumn, boolean isTrim) {
        StringBuilder sb = new StringBuilder();
        if ((introspectedColumn.isStringColumn() && isTrimStringsEnabled(introspectedColumn)) || isTrim) {
            sb.append("this.");
            sb.append(property);
            sb.append(" = ");
            sb.append(property);
            sb.append(" == null ? null : ");
            sb.append(property);
            sb.append(".trim();");
        } else {
            sb.append("this.");
            sb.append(property);
            sb.append(" = ");
            sb.append(property);
            sb.append(';');
        }
        return sb.toString();
    }


    private static boolean isTrimStringsEnabled(IntrospectedColumn column) {
        String trimSpaces = column.getProperties().getProperty(PropertyRegistry.MODEL_GENERATOR_TRIM_STRINGS);
        if (trimSpaces != null) {
            return isTrue(trimSpaces);
        }
        return isTrimStringsEnabled(column.getIntrospectedTable());
    }

    private static boolean isTrimStringsEnabled(IntrospectedTable table) {
        TableConfiguration tableConfiguration = table.getTableConfiguration();
        String trimSpaces = tableConfiguration.getProperties().getProperty(PropertyRegistry.MODEL_GENERATOR_TRIM_STRINGS);
        if (trimSpaces != null) {
            return isTrue(trimSpaces);
        }
        return isTrimStringsEnabled(table.getContext());
    }

    private static boolean isTrimStringsEnabled(Context context) {
        Properties properties = context
                .getJavaModelGeneratorConfiguration().getProperties();
        boolean rc = isTrue(properties
                .getProperty(PropertyRegistry.MODEL_GENERATOR_TRIM_STRINGS));
        return rc;
    }

    //公用注释
    private void annotate(Method method, String returnStr, String title, String description, String... params) {
        method.addAnnotation("/**");
        if (params != null && params.length > NumeralUtil.POSITIVE_ZERO) {
            for (String item : params) {
                method.addAnnotation(" * @param " + item);
            }
        }
        method.addAnnotation(" * @return " + returnStr);
        method.addAnnotation(" * @title " + title);
        method.addAnnotation(" * @description " + description);
        method.addAnnotation(" * @author " + author);
        method.addAnnotation(" * @datetime " + nowTime);
        method.addAnnotation(" * @version " + version);
        method.addAnnotation(" */");
    }


}
